import searchKeyService

sogou_data = None

def load_data(filename):
    print("数据加载中...")
    import pandas as pd
    b = ["访问时间", "用户ID", "查询词", "排名", "顺序号", "关键词", "类型"]
    # 实践的数据集
    data = pd.read_csv(filename, names=b, error_bad_lines=False, sep='\t')
    sogou_data = pd.DataFrame(data, columns=b)
    print("数据加载完毕！")
    return sogou_data


# 获取不同时间的访问量
def get_time_visit():
    sg_time = sogou_data.groupby('访问时间', as_index=False).size()
    # sg_time_sort = sg_time.sort_values(by='size', ascending=False)
    # print('不同时间段的网站访问量如下:\n')
    dict = {}
    dict['time'] = sg_time['访问时间'].tolist()
    dict['visit_count'] = sg_time['size'].tolist()
    return dict

# 获取不同时段搜索量
def get_quantum():
    sg_time = sogou_data.groupby('访问时间', as_index=False).size()
    sg_time['访问时间'] = sg_time['访问时间'].apply(lambda x: convert_time_to_part(x))
    sg_time = sg_time.groupby('访问时间', as_index=False).sum()
    list = []
    for row in sg_time.itertuples(index=False, name='访问时间'):
        list.append({'value': getattr(row, 'size'),'name': getattr(row, '访问时间')})
    print(list)
    return list

# 搜索记录词分析(词频,热词、热条)
# 按照高频词分类
def get_day_word() :
    # 不同时段的检索情况
    sg_word = sogou_data.groupby('查询词', as_index=False).size()
    sg_word_sort = sg_word.sort_values(by='size', ascending=False)
    print('当前日志中词频统计如下:\n')
    print(sg_word_sort)
    # --------在此返回热词
    print("\n访问 ", sg_word_sort.iloc[0, 0], "的人较多")
    # TODO 数据可视化 折线图
    list = []
    i = 10
    for row in sg_word_sort.itertuples(index=False, name='查询词'):
        if i==0:
            break
        list.append({'value': getattr(row, 'size'),'name': getattr(row, '查询词')})
        i = i-1
    print(list)
    return list

# 用户搜索次数分析
def get_users_word_time() :
    import pandas as pd
    sg_uid = sogou_data.groupby('用户ID', as_index=False).count()
    # print(sg_uid)
    sg_uid_data = pd.DataFrame({
        '用户ID': sg_uid['用户ID'],
        '访问次数': sg_uid['访问时间']
    })
    print('用户搜索关键词数量降序：', sg_uid_data)
    print(sg_uid_data.sort_values(by='访问次数', ascending=False).head(50))

# 个人搜索记录分析
def get_personal_log(user_id):
    # 建立用户id索引
    sogou_data_t = sogou_data.set_index(['用户ID'], drop=False)
    # 快速检索该用户的搜索记录信息
    cur_user = sogou_data_t.loc[user_id, ['查询词', '访问时间']]
    # print(cur_user)
    sg_personal = cur_user.groupby('查询词', as_index=False).size()
    sg_personal_sort = sg_personal.sort_values(by='size', ascending=False)
    # print("用户", user_id, '的查询记录如下:\n')
    # print(sg_personal_sort)

    # --------在此处分词统计其喜欢的类型（分析兴趣）,按照排序返回
    # 如果访问次数大于等于3，代表喜欢，则加入喜欢标签
    like_word = cut_word(sg_personal_sort)
    like_word = sorted(like_word.items(), key=lambda v: v[1], reverse = True)
    list = [] # 喜欢的关键词列表，访问词频大于等于3时加入，降序排序
    for i in like_word:
        if i[1] >= 3:
            list.append(i[0])
    print("\n该用户最近一天访问频率较高的词为：", list)

    # 分析其喜欢访问的时间段
    sg_personal = cur_user.groupby('访问时间', as_index=False).size()
    sg_personal_sort = sg_personal.sort_values(by='size', ascending=False)
    # print("\n用户", user_id, '的查询记录如下:\n')
    # print(sg_personal_sort)
    # -------------在此处分析其喜欢活动的时间(可以分段[0,4] 深夜 [4,7] 凌晨 [7,11]早晨 12中午 [13,16]下午 [17,19] 傍晚 [20,23]夜晚 )
    visist_hour = int(sg_personal_sort.iloc[0, 0])
    time = convert_time_to_part(visist_hour)
    print("\n该用户喜欢在", time, "时访问搜索引擎")

    return {'hot_words': like_word, 'quantum': time}


# -------------在此处分析其活动的时间(可以分段[0,4] 深夜 [4,7] 凌晨 [7,11]早晨 12中午 [13,16]下午 [17,19] 傍晚 [20,23]夜晚 )
def convert_time_to_part(visist_hour):
    if visist_hour in range(0, 4):
        time='深夜'
    elif visist_hour in range(4,7):
        time='凌晨'
    elif visist_hour in range(7,12):
        time='早晨'
    elif visist_hour == 12:
        time='中午'
    elif visist_hour in range(13,17):
        time='下午'
    elif visist_hour in range(17,20):
        time='傍晚'
    else:
        time='夜晚'
    return time

# 分词提取关键
def cut_word(arr):
    import jieba
    t_arr = {}
    for item in arr['查询词']:
        for word in jieba.lcut(item):
            if word in t_arr.keys():
                t_arr[word] += 1
            else:
                t_arr[word] = 1
    print(t_arr)
    return t_arr

# 定时优化关键词任务
def optimize_keyword():
    # 遍历提取用户id,分析每个用户的行为并且持久化
    import pandas as pd
    sg_uid = sogou_data['用户ID'].unique()
    for i in sg_uid:
        user_behavior_analysis(i)


# ----------------------------------分析一个用户的行为 start ----------------------------------
def user_behavior_analysis(user_id):
    # 建立用户id索引
    sogou_data_t = sogou_data.set_index(['用户ID'], drop=True)
    # print(sogou_data_t)
    # 快速检索该用户的搜索记录信息
    cur_user = sogou_data_t.loc[user_id, ["访问时间", "查询词", "排名", "顺序号", "关键词", "类型"]]
    # print(cur_user)
    # 1.1 注意，一个用户可能搜索多个关键词，因此评判标准以每个词为准。for循环每个词
    # 重新以关键词再建立索引
    try:
        for keyword in cur_user['查询词'].unique():
            # print(keyword)
            # 取出关键词所在列
            cur_cluster = cur_user[cur_user['查询词'].isin([keyword])].set_index(['关键词'], drop=True)
            cur_cluster['分值'] = cur_cluster.apply(lambda x: convert_rank(x['顺序号'], x['排名']), axis=1)
            # print(cur_cluster)
            # 持久化保存至数据库
            # key_id\rank_id\type\score
            cur_cluster.apply(lambda x: persistence_data(x['查询词'], x['排名'], x['分值']), axis=1)
    # 可能存在仅点击一次的情况
    except:
        keyword = cur_user['查询词']
        cur_user['分值'] =  convert_rank(cur_user['顺序号'], cur_user['排名'])
        # print(cur_user)
        # 持久化保存至数据库
        # key_id\rank_id\type\score
        persistence_data(cur_user['查询词'], cur_user['排名'], cur_user['分值'])


# 持久化数据到数据库
def persistence_data(keyword, rank, score, type=0):
    # 当得分为0时，表示正常，无需加入异常词
    if score == 0:
        return
    # TODO 暂时数据没有填充,后续做一下数据填充,还有type的选择
    # from persistence import searchKeyDao
    # searchKeyDao.get_word_id(keyword)
    # 当有数据填充后,下面两行删除!!!!
    import random
    key_id = random.randint(100, 120)

    from persistence import sqlUtil
    db_name = 'kw_cpt_user'
    conn, cur = sqlUtil.get_cur(db_name)
    # 无则插入，有则更新
    sql = 'INSERT INTO user_search_feedback (key_id, rank_id, type, score) VALUES ({}, {}, {}, {}) ON DUPLICATE KEY UPDATE score = score+1;;'
    try:
        conn, cur = sqlUtil.get_cur(db_name)
        cur.execute(sql.format(key_id, rank, type, score))
        conn.commit()
        # print("事务执行成功!")
    except Exception as e:
        conn.rollback()
        # print('事务处理失败', e)
    finally:
        sqlUtil.close_db(conn, cur)


'''
一共10条，第一次访问10，则
一般数据库的词条至少为50条，则可以按照rank划分等级：
第一梯队： 1<=rank<=5 [1,5]
第二梯队： 6<=rank<=10 [6,10]
第三梯队： 11<=rank<=20 [11,20]
第四梯队： 21<=rank [21,＋∞]

评价：
    指标：（order，梯队数）如（1，2）即第一次点了第二梯队的值
    正常情况下：
        第【一】次       - 第（一）梯队: [1,5]
        第【二、四】次    - 第（一、二）梯队: [1,10]
        第【五、七】次    - 第（一、二、三）梯队: [1,20]
        第【八次及其上】次 - 第（一、二、三、四）梯队: [1,＋∞]
    不符合上述情况的可以视为异常词：
        (1,2) rank奖励+1,当前关键词异常+1, (给rank低的词加分，提升排名) (同时给当前搜索关键词惩罚分)       
        (1,3) rank奖励+2,当前关键词异常+2,
        (1,4) rank奖励+3,当前关键词异常+3.
        ...
        总结规律：
        1.order<梯度数，正常
        2.order>梯度数，order-梯度数=分值，rank奖励+分值，当前搜索关键词惩罚+分值。
'''
def convert_rank(order, rank):
    if 1 <= rank <= 5:
        level_r=1
    elif 6 <= rank <= 10:
        level_r=2
    elif 11 <= rank <= 20:
        level_r=3
    else:
        level_r=4

    if order == 1:
        level_o = 1
    elif 2<= order <=4:
        level_o = 2
    elif 5<= order <=7:
        level_o = 3
    else:
        level_o = 4

    # 出现异常,赋分
    if level_o > level_r:
        return level_o - level_r
    # 无异常,不赋分
    return 0
# ----------------------------------分析一个用户的行为 end ----------------------------------
'''
获取统计报表
'''
def get_reports():
    # 获取搜索总记录数
    search_count = len(sogou_data)
    visit_count = len(sogou_data['用户ID'].unique())

    sg_word = sogou_data.groupby('查询词', as_index=False).size()
    sg_word_sort = sg_word.sort_values(by='size', ascending=False)

    hot_word = sg_word_sort.iloc[0, 0]

    db_name = 'kw_cpt_user'
    # 默认设置阈值为20，即分数大于20的算作异常词
    sql = 'select * from user_search_feedback where score > 20'
    from persistence import sqlUtil
    conn, cur = sqlUtil.get_cur(db_name)
    cur.execute(sql)
    # print(cur.fetchall())
    conn.commit()
    # print("事务执行成功!")
    ex_word = len(cur.fetchall())

    # 装填数据返回
    return {
        "search_count"  :   search_count,
        "visit_count"   :   visit_count,
        "hot_word"      :   hot_word,
        "ex_word_count" :   ex_word
    }

'''
获取异常词报表
{'id': 100, '关键词': '奥凯航空', '罚分': 107}
'''
def get_ex_word_list():
    db_name = 'kw_cpt_user'
    # 默认设置阈值为20，即分数大于20的算作异常词
    sql = 'select * from user_search_feedback where score > 20'
    from persistence import sqlUtil
    conn, cur = sqlUtil.get_cur(db_name)
    import pandas as pd
    data_sql = pd.read_sql(sql, conn)
    # print(data_sql)
    # 此处可以对结果集进行分析处理
    # 如果某个关键词的rank词条很多，即select key_id得到的记录很多，说明该词异常，应该给予异常惩罚
    # 阈值可以设定为异常词的均值，大于均值的给予该词惩罚。
    data_sql_t = data_sql.groupby('key_id').sum()
    df = data_sql_t.drop(columns=['rank_id', 'type'])
    df = df.rename(columns={'score': '罚分'})
    list = []
    index = 0
    for i in df.index:
        keyword = searchKeyService.get_id_to_word(i)
        list.append({'id': i, '关键词': keyword, '罚分': df.iloc[index, 0]})
        index += 1
    print(list)
    conn.close()
    cur.close()
    return list

'''
获取异常词列表
'''
def get_ex_word_detail(key_id):
    '''
    根据id去select异常表
    取出rankid、type和score
    根据type和id查询对应关键词列表，并用rank_id索引
    返回keyword、rankword、分值
    '''
    db_name = 'kw_cpt_user'
    # 根据keyid取出所有异常词
    sql = 'select * from user_search_feedback where key_id={}'
    from persistence import sqlUtil
    conn, cur = sqlUtil.get_cur(db_name)
    import pandas as pd
    data_sql = pd.read_sql(sql.format(key_id), conn)
    print(data_sql['rank_id'])

def convert_rank_id_to_word(key_id, rank_id, type):
    # 中介
    if type == 0:
        print()

# 测试用
if __name__ == '__main__':
    # sogou_data = load_data('../static/test.useful.new')
    # sogou_data = load_data('../static/test.useful.new')
    # optimize_keyword()
    # user_behavior_analysis('a8a1a58653dcc4c3a99fdd1ffdffb5f9')
    # get_day_word()
    # print(get_reports())
    # get_ex_word_list()
    # get_personal_log('a8a1a58653dcc4c3a99fdd1ffdffb5f9')
    print(searchKeyService.get_mid_key(3))
    # get_ex_word_detail(100)